package cz.muni.fi.pa165.musiclibrary.impl.database.dao;

import java.util.List;

import javax.annotation.Nonnull;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

import cz.muni.fi.pa165.musiclibrary.impl.database.entity.IAlbum;
import cz.muni.fi.pa165.musiclibrary.impl.database.entity.IArtist;
import cz.muni.fi.pa165.musiclibrary.impl.database.entity.IGenre;
import cz.muni.fi.pa165.musiclibrary.impl.database.entity.ISong;
import cz.muni.fi.pa165.musiclibrary.impl.database.entity.Song;

/**
 *
 * @author Martin Szabo
 * 2012-10-12T19:22:53+0200
 */
@Repository
public class SongDAO extends AbstractDAO implements ISongDAO {
    /**
     * Factory for creating {@link EntityManager}.
     */
    private EntityManager em;
    
    /**
     * Inject {@link EntityManager} instance;
     */
    @PersistenceContext
    @Required
    @Override
    public void setEntityManager(final EntityManager entityManager) {
        this.em = entityManager;
    }
    
    
    @Override
    public void create(@Nonnull final ISong song) throws DataAccessException{
        Validate.isTrue(song != null, "Song should not be null.");
        Validate.isTrue(song.getIdSong() == null, "Song identifier should be null.");
        em.persist(song);

    }

    @Override
    public void update(@Nonnull final ISong song) throws DataAccessException{
        Validate.isTrue(song != null, "Song should not be null.");
        Validate.isTrue(song.getIdSong() != null, "Song identifier should not be null.");
        final Query update = em.createQuery("UPDATE Song s SET s.title = :title, "
                + " s.bitrate = :bitrate, s.lengthSong = :length, s.trackNumber = :track_number,"
                + " s.comment = :comment,"
                + " s.album = :album,"
                + " s.genre = :genre,"
                + " s.artist = :artist"
                + " WHERE s.idSong = :id_song");
        update.setParameter("title", song.getTitle())//
                .setParameter("bitrate", song.getBitrate())//
                .setParameter("length", song.getLength())//
                .setParameter("track_number", song.getTrackNumber())//
                .setParameter("comment", song.getComment())//
                .setParameter("album", song.getAlbum())//
                .setParameter("genre", song.getGenre())//
                .setParameter("artist", song.getArtist())
                .setParameter("id_song", song.getIdSong());
        update.executeUpdate();

    }

    @Override
    public void delete(@Nonnull final ISong song) throws DataAccessException{
        Validate.isTrue(song != null, "Song should not be null.");
        Validate.isTrue(song.getIdSong() != null, "Song identifier should not be null.");
        final Query delete = em.createQuery("DELETE FROM Song s WHERE s.idSong = :id_song");
        delete.setParameter("id_song", song.getIdSong());
        delete.executeUpdate();
    }

    @Override
    public ISong getById(@Nonnull final Long id) throws DataAccessException{
        Validate.isTrue(id != null, "Identifier should not be null.");
        final ISong song = em.find(Song.class, id);
        return song;
    }

    @Override
    public List<ISong> getAll() throws DataAccessException{
        final List<ISong> songs = em.createQuery("SELECT s FROM Song s").getResultList();
        em.close();
        return songs;
    }

    @Override
    public List<ISong> getByTitle(@Nonnull final String title) throws DataAccessException{
        Validate.isTrue(StringUtils.isNotBlank(title), "String to search for should not be null or empty.");
        Validate.isTrue(title.length() > 2);
        final Query get = em.createQuery("SELECT s FROM Song s WHERE LOWER(s.title) LIKE :title");
        get.setParameter("title", "%" + title.toLowerCase() + "%");
        final List<ISong> songs = get.getResultList();
        return songs;
    }

    @Override
    public List<ISong> getByAlbum(IAlbum album) throws DataAccessException{
        Validate.isTrue(album != null, "Album should not be null.");
        final Query get = em.createQuery("SELECT s FROM Song s WHERE s.album  = :album");
        get.setParameter("album", album);
        final List<ISong> songs = get.getResultList();
        return songs;
    }

    @Override
    public List<ISong> getByArtist(IArtist artist) throws DataAccessException{
        Validate.isTrue(artist != null, "Album should not be null.");
        final Query get = em.createQuery("SELECT s FROM Song s WHERE s.artist  = :artist");
        get.setParameter("artist", artist);
        final List<ISong> songs = get.getResultList();
        return songs;
    }

    @Override
    public List<ISong> getByGenre(IGenre genre) throws DataAccessException{
       Validate.isTrue(genre != null, "Album should not be null.");
        final Query get = em.createQuery("SELECT s FROM Song s WHERE s.genre  = :genre");
        get.setParameter("genre", genre);
        final List<ISong> songs = get.getResultList();
        return songs;
    }
}